#include "head.h"
//用户下载，服务端向客户端发文件
int send_file(const char *file_name, off_t file_size, int net_fd){
    int fd = open(file_name, O_RDWR);
    if(fd == -1){
        return -1;
    }

    //接收客户端发来的偏移量(客户端已经接收了多少)
    off_t offset;
    recv(net_fd, &offset, sizeof(off_t), MSG_WAITALL);

    //发送本地要发送的文件大小
    send(net_fd, &file_size, sizeof(off_t), MSG_NOSIGNAL);
    //发送文件哈希值
    send(net_fd, file_name, FILE_HASH_SIZE, MSG_NOSIGNAL);
    //发送文件
    sendfile(net_fd, fd, &offset, file_size - offset);

    close(fd);
    return 0;
}

//用户上传，服务端接收客户端的文件
int recv_file(MYSQL_ROW row, int user_id, int net_fd, request_t *request, MYSQL *mysql){
    MYSQL_RES *res2;
    MYSQL_ROW row2;

    //接收文件哈希值
    char client_file_hash[FILE_HASH_SIZE + 1] = {0};
    recv(net_fd, client_file_hash, FILE_HASH_SIZE, MSG_WAITALL);

    char query[1024] = {0};
    //判断是否可以秒传
    int flag = 0;
    if(row != NULL && atoi(row[8]) == 1){
        flag = 1;
        send(net_fd, &flag, sizeof(int), MSG_NOSIGNAL);
        return 0;
    }
    if(row == NULL){
        bzero(query, sizeof(query));
        sprintf(query, "select * from files \
                where file_hash = '%s' and file_complete = 1 \
                and delete_flag = 1", client_file_hash);
        mysql_query(mysql, query);
        res2 = mysql_store_result(mysql);
        row2 = mysql_fetch_row(res2);
        if(row2 != NULL){
            flag = 1;
            send(net_fd, &flag, sizeof(int), MSG_NOSIGNAL);
            off_t file_size = atoi(row2[9]);
            mysql_free_result(res2);

            //获取父id
            bzero(query, sizeof(query));
            sprintf(query, "select id from files \
                    where user_id = %d and path = '%s'",
                    user_id, request->path);
            mysql_query(mysql ,query);
            res2 = mysql_store_result(mysql);
            row2 = mysql_fetch_row(res2);
            int father_id = atoi(row2[0]);
            mysql_free_result(res2);

            //添加新的表项
            bzero(query, sizeof(query));
            char str[160] = {0};
            strcpy(str, request->path);
            if(strcmp(str, "/")){
                strcat(str, "/");
            }
            strcat(str, request->args);
            sprintf(query, "insert into files values \
                    (null, '%s', %d, %d, '%s', 1, '%s', now(), 1, %ld, 1)",
                    request->args, user_id, father_id, str,
                    client_file_hash, file_size);
            mysql_query(mysql, query);
            return 0;
        }
    }
    send(net_fd, &flag, sizeof(int), MSG_NOSIGNAL);

    //接收客户端要上传的文件大小
    off_t file_size;
    recv(net_fd, &file_size, sizeof(off_t), MSG_WAITALL);

    off_t offset = 0;
    if(row != NULL){
        offset = atoi(row[9]);
    }
    //发送偏移量
    send(net_fd, &offset, sizeof(off_t), MSG_NOSIGNAL);

    int fd = open(client_file_hash, O_RDWR | O_CREAT, 0666);

    ftruncate(fd, file_size);

    char *p =(char *)mmap(NULL, file_size, PROT_READ | PROT_WRITE,
                          MAP_SHARED, fd, 0);
    char *curr = p + offset;

    //接收文件, 接收  文件总大小-已经上传的大小
    int recv_count = recv(net_fd, curr, file_size - offset, MSG_WAITALL);
    // 已经上传大小 += 再次上传的大小
    offset += recv_count;
    ftruncate(fd, offset);
    munmap(p, file_size);
    close(fd);

    int file_complete = 0;
    if(offset == file_size){
        char server_file_hash[FILE_HASH_SIZE + 1];
        hash_count(client_file_hash, server_file_hash, sizeof(server_file_hash));
        if(!strcmp(client_file_hash, server_file_hash)){
            //用户上传成功
            file_complete = 1;
        }
        send(net_fd, &file_complete, sizeof(int), MSG_NOSIGNAL);
    }

    //服务端原本不存在该文件，添加新表项
    if(row == NULL){
        //获取父id
        bzero(query, sizeof(query));
        sprintf(query, "select id from files \
                where user_id = %d and path = '%s'", 
                user_id, request->path);
        mysql_query(mysql ,query);
        res2 = mysql_store_result(mysql);
        row2 = mysql_fetch_row(res2);
        int father_id = atoi(row2[0]);
        mysql_free_result(res2);

        //添加新的表项
        bzero(query, sizeof(query));
        char str[160] = {0};
        strcpy(str, request->path);
        if(strcmp(str, "/")){
            strcat(str, "/");
        }
        strcat(str, request->args);
        sprintf(query, "insert into files values \
                (null, '%s', %d, %d, '%s', 1, '%s', now(), %d, %ld, 1)", 
                request->args, user_id, father_id, str, 
                client_file_hash, file_complete, offset);
        mysql_query(mysql, query);
    }
    //服务端原本存在该文件，修改信息
    else{
        //修改表项
        char str[160] = {0};
        strcpy(str, request->path);
        if(strcmp(str, "/")){
            strcat(str, "/");
        }
        strcat(str, request->args);
        bzero(query, sizeof(query));
        sprintf(query, "update files set \
                file_complete = %d, file_size = %ld \
                where filename = '%s' and user_id = %d \
                and path = '%s' and delete_flag = 1",
                file_complete, offset, request->args, user_id, str);
        mysql_query(mysql, query);
    }

    return 0;
}
